﻿using System;
using System.Runtime.Remoting.Messaging;
using System.Transactions;
//using RAMIS.Framework.Core;

namespace Sample.Common.Transaction
{
    public abstract class TransactionScopeAbstractWrapper : IDisposable
    {
        private const string TransactionScopeWrapperKey = "__TransactionScopeWrapper";

        protected TransactionScopeAbstractWrapper()
            : this(TransactionScopeOption.Required,
                IsolationLevel.ReadCommitted,
                new TimeSpan(0, 0, 30))
        {
        }

        protected TransactionScopeAbstractWrapper(TransactionScopeOption scopeOption,
            IsolationLevel isolationLevel,
            TimeSpan timeout)
        {
            ScopeOption = scopeOption;
            IsolationLevel = isolationLevel;
            Timeout = timeout;
            IsDisposed = false;

            var current = CallContext.GetData(TransactionScopeWrapperKey) as TransactionScopeAbstractWrapper;

            if (current == null || current.IsDisposed)
            {
                AppContext.Current.DbTransactionId = Guid.NewGuid().ToString();
                CallContext.SetData(TransactionScopeWrapperKey, this);
            }
        }

        public IsolationLevel IsolationLevel { get; private set; }
        public TimeSpan Timeout { get; private set; }
        public TransactionScopeOption ScopeOption { get; private set; }

        public abstract bool IsCompleted { get; protected set; }

        public static TransactionScopeAbstractWrapper Current
        {
            get { return CallContext.GetData(TransactionScopeWrapperKey) as TransactionScopeAbstractWrapper; }
        }

        public bool IsDisposed { get; private set; }

        public void Dispose()
        {
            Dispose(true);
            IsDisposed = true;

            //Clear transaction id. It could not be called after complete, because maybe there is a next INNER scope.
            var current = CallContext.GetData(TransactionScopeWrapperKey) as TransactionScopeAbstractWrapper;

            if (current == this)
            {
                AppContext.Current.DbTransactionId = Guid.Empty.ToString();
            }

            GC.SuppressFinalize(this);
        }

        protected abstract void Dispose(bool isDisposing);
        public abstract void Complete();
    }
}